﻿#ifndef __SS_AUTO_PTR_H__
#define __SS_AUTO_PTR_H__
#include "../thread/threadLock/ssAtomic.h"
#include"../ssAssert.h"

namespace StarSeeker
{

template<typename T>
class ssAutoPtr
{  
	struct ptr_t
	{
		ssAtomicl	ref;
		T*			ptr;
		ptr_t()
			:ref(1), ptr(0)
		{
		}
	};
public:
	ssAutoPtr()
	{
		m_pRef = 0;
	}

	~ssAutoPtr()
	{
		DecRef();
	}

	ssAutoPtr(const ssAutoPtr& p2)
	{
		m_pRef = 0;
		CopyFrom(p2);
	}

	ssAutoPtr(T* t2)
	{
		m_pRef = 0;
		Create(t2);
	}

	void operator = (const ssAutoPtr& p2)
	{
		CopyFrom(p2);
	}

	void operator = (T* t2)
	{
		Create(t2);
	}

	T* operator -> ()
	{
		return m_pRef->ptr;
	}
	T& operator * ()
	{
		return *m_pRef->ptr;
	}

	void IncRef()
	{
		if (m_pRef)
			++m_pRef->ref;
	}
	//要赋值必然会有个引用存在,那么赋值时绝对大于等于1。0的时候不会变成1,除非new的时候。
	void DecRef()
	{
		if (m_pRef)
		{
			if (m_pRef->ref.Value() > 0)
			{
				--m_pRef->ref;
			}
			SS_ASSERT(m_pRef->ref.Value() >= 0);
			if (m_pRef->ref.Value() == 0)
			{
				SS_SAFE_DELETE(m_pRef->ptr)
				SS_SAFE_DELETE(m_pRef)
			}
		}
	}

private:
	bool Create(T* t)
	{
		if (!m_pRef && t)
		{
			m_pRef = new ptr_t;
			m_pRef->ptr = t;
			return true;
		}
		return false;
	}

	bool CopyFrom(const ssAutoPtr& p2)
	{
		if (p2.m_pRef)
		{
			if (!this->m_pRef)
			{
				this->m_pRef = p2.m_pRef;
				this->IncRef();
			}
			else
			{
				this->DecRef();
				this->m_pRef = p2.m_pRef;
				this->IncRef();
			}
			return true;
		}
		return false;
	}


	ptr_t*	m_pRef;
};

}
#endif
